2023/12/236207字符

DOM

DOM —— Document Object Model 文档对象模型 (用来操作html、xml功能一类对象的集合)

文档对象模型

将HTML文件解析成一个一个节点对象,再配合JS语法就可以操作文档中的内容了

  • HTML中所有的东西都是一个节点,所有的节点都由一个对象构成,包括 document Document.__proto__ = Node
    • Node Document HTMLDocument Element Attr

分类:

  • 动态集合: children, childNodes, getElementByTagName
  • 静态集合(监听不到节点变化): querySelectorAll

查看元素节点

document  // 代表整个文档
document.getElementById('id');  // 元素 id 在 IE8 以下的浏览器,不区分 id 大小写,而且也返回匹配 name 的属性
document.getElementsByTagName('div')[0];  // 标签名
document.getElementsByName('name')[0];  // name 需注意:只有部分标签name可生效(表单,表单元素,img,iframe)
document.getElementsByClassName('class')[0];  // 类名 -> ie8和ie8以下的ie版本中没有,可以多个class一起
document.querySelector('div>span strong.demo');  // css选择器   在ie7和ie7以下的版本中没有 解决不了实时性问题
document.querySelectorAll('div>span strong.demo');  // css组选择器   在ie7和ie7以下的版本中没有 解决不了实时性问题

节点类型

  • 元素节点 - 1
  • 属性节点 - 2
  • 文本节点 - 3
  • 注释节点 - 8
  • document - 9
  • DocumentFragment - 11

遍历节点树

div.parentNode  // 父节点(最顶端的 parentNode 为 #document)
div.childNodes  // 子节点们
div.fristChild  // 第一个子节点
div.lastChild  // 最后一个子节点
div.nextSibling  // 后一个兄弟节点
div.previousSibling  // 前一个兄弟节点

遍历元素节点树(IE8 及以下不兼容,除 .children)

div.parentElement  // 返回当前元素父元素节点
div.children  // 只返回当前元素的元素子节点
div.childElementCount  // 当前元素节点的子元素 (div.childElementCount === div.children.length)
div.fristElementChild  // 第一个元素节点
div.lastElementChild  // 最后一个元素节点
div.nextElementSibling  // 后一个兄弟元素节点
div.previousElementSibling  // 前一个兄弟元素节点

节点的四个属性

  • div.nodeName :元素标签名,以大写形式表示(只读)
  • div.nodeValue :text 或 comment 节点的文本内容(可读写)
  • div.nodeType :该节点的类型(只读)
  • div.attributes :elment 节点的属性集合
  • div.hasChildNodes() :hasChildNodes() 方法可在某节点用于任何子节点时返回 true,否则返回 false

dom 增 插 删 替换

// <div class="class"><strong></strong><span></span><i></i></div>
// 增
    document.createElement('div');  // 增加标签节点
    document.createTextNode('div');  // 增加文本节点
    document.createComment('div');  // 增加注释节点
    document.createDocumentFragment('div');  // 增加文档碎片节点
// 插
    div.appendChild(p);  // 插入节点(若一个元素插入两个位置会发生剪切作用)
    div.insertBefore(p, span);  // 在 b 节点前插入节点 a
// 删
    span.removeChild();  // 被剪切(谋杀)
    span.remove();  // 被删除(自杀)
// 替换
    div.replace(em, span);  // 新节点 a 替换 b 节点

Element 节点属性

div.innerHTML  // 读取 HTML 结构,将 element 节点取出
div.innerHTML = "<span style='width:30px;height:25px;background-color:#f00;color:#fff';>string</span>";  // 覆盖内容
div.innerHTML += 'string';  // 添加内容
div.innerText = 'string';  // 覆盖文本(包括标签) 火狐老版本不兼容
div.textContent = 'string';  // 火狐提出覆盖文本的方法 但(IE)不兼容

Element节点方法

div.setAttribute('id', 'only');  // 添加属性(可设置系统没有的)
div.getAttribute('class');  // 取出属性
div.className = 'class';  // 可读写 class

获取一个元素被点击的次数

// <a herf="#" class="demo" data-log=""></a>
var a = document.getElementsByTagName('a');
a.onclick = function () {
    console.log(this.getAttribute('data-log'));
}

封装一个方法,查看第 n 层父元素节点

// <div><strong><span><i></i></span></strong></div>
function reParent (elem, n) {
    while(elem && n){
        elem = elem.parentElement;  // IE 父元素节点选择
        n --;
    }
    return elem;
}
var i = document.getElementsByTagName('i')[0];
console.log(reParent(i, 2));  //--> <strong></strong>
console.log(reParent(i, 6));  //--> null

封装一个 myChildren 功能,解决以前部分浏览器得兼容性问题

// <div><strong><span><i></i></span></strong></div>
Element.prototype.myChildren = function () {
    var child = this.childNodes;  // 获得 body 子元素集合
    var len = child.length;
    var arr = [];
    for (var i = 0; i < len; i++) {
        if (child[i].nodeType == 1) {
            arr.push(child[i]);
        }
    }
    return arr;
}
var div = document.getElementsByTagName('div')[0];
console.log(div.myChildren());

封装函数,返回元素 e 的第 n 个兄弟元素节点,n为正返回后面的兄弟元素节点,n为负返回前面的,n为0返回自己

function retSibling (e, n) {
    while (e && n) {
        if (n > 0) {
            if (e.nextElementSibling) {
                e = e.nextElementSibling;
            } else {
                for (e.nextSibling; e && e.nextSibling != 1; e = e.nextSibling);
            }  // 解决IE兼容性问题
            n --;
        }else {
            if (e.previousElementSibling) {
                e = e.previousElementSibling;
            } else {
                for (e.previousSibling; e && e.previousSibling != 1; e = e.previousSibling);
            }
            n ++;
        }
    }
    return e;
}
var div = document.getElementsByTagName('div')[1];
console.log(retSibling(div, 2));